﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace CS633_Final_Project
{
    class MathUtil
    {
        /// <summary>
        /// Returns the length of a line segment.
        /// </summary>
        /// <param name="line">Line to measure.</param>
        /// <returns>length of a line segment.</returns>
        public static float SegmentLength(Line line)
        {
            float dx = Math.Abs(line.P.X - line.Q.X);
            float dy = Math.Abs(line.P.Y - line.Q.Y);

            return (float)Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2));
        }

        /// <summary>
        /// Returns the intersection between two line segments if the exist.
        /// Adapted from: http://workshop.evolutionzone.com/2007/09/10/code-2d-line-intersection/
        /// </summary>
        /// <param name="s1">Line Segment 1</param>
        /// <param name="s2">Line Segment 2</param>
        /// <returns>Intersection point if it exists.</returns>
        public static PointF Intersection(Line s1, Line s2)
        {
            return findIntersection(s1.P, s1.Q, s2.P, s2.Q);
        }

        public static PointF findIntersection(PointF p1, PointF p2, PointF p3, PointF p4)
        {
            PointF pt = new Point(0, 0);
            float xD1, yD1, xD2, yD2, xD3, yD3;
            float dot, deg, len1, len2;
            float segmentLen1, segmentLen2;
            float ua, ub, div;

            // calculate differences  
            xD1 = p2.X - p1.X;
            xD2 = p4.X - p3.X;
            yD1 = p2.Y - p1.Y;
            yD2 = p4.Y - p3.Y;
            xD3 = p1.X - p3.X;
            yD3 = p1.Y - p3.Y;

            // calculate the lengths of the two lines  
            len1 = (float) Math.Sqrt(xD1 * xD1 + yD1 * yD1);
            len2 = (float) Math.Sqrt(xD2 * xD2 + yD2 * yD2);

            // calculate angle between the two lines.  
            dot = (xD1 * xD2 + yD1 * yD2); // dot product  
            deg = dot / (len1 * len2);

            // if abs(angle)==1 then the lines are parallell,  
            // so no intersection is possible  
            if (Math.Abs(deg) == 1)
                pt = new PointF(float.NegativeInfinity, float.NegativeInfinity);
            else
            {
                // find intersection Pt between two lines  
                div = yD2 * xD1 - xD2 * yD1;
                ua = (xD2 * yD3 - yD2 * xD3) / div;
                ub = (xD1 * yD3 - yD1 * xD3) / div;
                pt.X = p1.X + ua * xD1;
                pt.Y = p1.Y + ua * yD1;

                // calculate the combined length of the two segments  
                // between Pt-p1 and Pt-p2  
                xD1 = pt.X - p1.X;
                xD2 = pt.X - p2.X;
                yD1 = pt.Y - p1.Y;
                yD2 = pt.Y - p2.Y;
                segmentLen1 = (float)(Math.Sqrt(xD1 * xD1 + yD1 * yD1) + Math.Sqrt(xD2 * xD2 + yD2 * yD2));

                // calculate the combined length of the two segments  
                // between Pt-p3 and Pt-p4  
                xD1 = pt.X - p3.X;
                xD2 = pt.X - p4.X;
                yD1 = pt.Y - p3.Y;
                yD2 = pt.Y - p4.Y;
                segmentLen2 = (float)(Math.Sqrt(xD1 * xD1 + yD1 * yD1) + Math.Sqrt(xD2 * xD2 + yD2 * yD2));

                // if the lengths of both sets of segments are the same as  
                // the lenghts of the two lines the point is actually  
                // on the line segment.  

                // if the point isn't on the line, return null  
                if (Math.Abs(len1 - segmentLen1) > 0.01 || Math.Abs(len2 - segmentLen2) > 0.01)
                    pt = new PointF(float.NegativeInfinity, float.NegativeInfinity);
            }

            // return the valid intersection  
            return pt;  
        }
    }
}
